/*
 *
 *      Copyright (c) 2018-2025, st All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: st
 *
 */

package com.mkh.st.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mkh.st.admin.api.dto.*;
import com.mkh.st.admin.api.entity.SysRole;
import com.mkh.st.admin.api.entity.SysRoleMenu;
import com.mkh.st.admin.api.entity.SysUserRole;
import com.mkh.st.admin.api.util.TreeUtil;
import com.mkh.st.admin.api.vo.*;
import com.mkh.st.admin.mapper.SysRoleMapper;
import com.mkh.st.admin.mapper.SysUserMapper;
import com.mkh.st.admin.service.*;
import com.mkh.st.common.core.constant.CommonConstants;
import com.mkh.st.common.core.constant.enums.*;
import com.mkh.st.common.core.exception.BizException;
import com.mkh.st.common.core.util.R;
import com.mkh.st.common.security.service.DaoismUser;
import com.mkh.st.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author st
 * @since 2017-10-29
 */
@Service
@AllArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

	private final SysRoleMenuService roleMenuService;

	private final SysRoleMapper sysRoleMapper;

	private final SysUserMapper sysUserMapper;

	private final SysUserService sysUserService;

	private final SysUserRoleService sysUserRoleService;

	private final List<Long> scopeIds= Arrays.asList(ScopeEnum.USER.getId());

    @Override
    public R<IPage<RoleInfoVO>> getRoleInfo(Page page, RolePageDTO dto) {
		IPage<RoleInfoVO> iPageInfo=sysRoleMapper.getPageInfo(page,dto);
		if(CollectionUtil.isNotEmpty(iPageInfo.getRecords())){
			iPageInfo.getRecords().forEach(entity -> {
				entity.setHierarchyName(getHierarchyName(entity.getRoleId()));
			});
		}
		return R.ok(iPageInfo);
    }

	@Override
	public List<RoleInfoVO> getRoleInfoList(RolePageDTO dto) {
		List<SysRole> roleList = sysRoleMapper.selectList(Wrappers.<SysRole>lambdaQuery()
				.like(StrUtil.isNotBlank(dto.getRoleName()),SysRole::getRoleName,dto.getRoleName())
				.like(StrUtil.isNotBlank(dto.getRoleCode()),SysRole::getRoleCode,dto.getRoleCode())
				.eq(SysRole::getDelFlag,CommonConstants.ZERO).eq(SysRole::getTenantId,dto.getTenantId()));
		List<RoleInfoVO> list=new ArrayList<>();
		if (CollectionUtil.isNotEmpty(roleList)){
			roleList.forEach( item ->{
				RoleInfoVO vo=BeanUtil.toBean(item,RoleInfoVO.class);
				vo.setHierarchyName(getHierarchyName(item.getRoleId()));
				list.add(vo);
			});
		}
		return list;
	}


	@Override
	public List<RoleTree> getRoleInfoTree(RolePageDTO dto) {
		dto.setTenantId(SecurityUtils.getUser().getTenantId());
		return TreeUtil.buildRoleTree(baseMapper.getRoleTree(dto), CommonConstants.MENU_TREE_ROOT_ID);
	}

	@Override
	public RoleDetailVO getSysRoleDetail(Long roleId) {
		SysRole sysRole=sysRoleMapper.selectById(roleId);
		RoleDetailVO vo=BeanUtil.toBean(sysRole,RoleDetailVO.class);
		SysRole parentRole=sysRoleMapper.selectById(sysRole.getParentId());
		if(ObjectUtil.isNotNull(parentRole)){
			vo.setParentName(parentRole.getRoleName());
		}
		vo.setHierarchyName(getHierarchyName(roleId));
		return vo;
	}

	@Override
	public String getHierarchyName(Long roleId) {
		List<String> list=sysRoleMapper.getParentList(roleId);
		StringBuilder stringBuilder=new StringBuilder();
		if(CollectionUtil.isEmpty(list)){
			return "";
		}
		list.forEach(item ->{
			stringBuilder.append(CommonConstants.SPLIT+item);
		});
		return stringBuilder.toString().substring(CommonConstants.ONE);
	}

	@Override
	public R<List<RoleListVO>> getSysRoleList() {
		List<SysRole> list=sysRoleMapper.selectList(Wrappers.<SysRole>lambdaQuery()
				.eq(SysRole::getTenantId,SecurityUtils.getUser().getTenantId()).eq(SysRole::getDelFlag,CommonConstants.NOT_DEL));
		List<RoleListVO> roleListVOS=new ArrayList<>();
		if(CollectionUtil.isEmpty(list)){
			list.forEach(item ->{
				RoleListVO vo=BeanUtil.toBean(item,RoleListVO.class);
				roleListVOS.add(vo);
			});
			return R.ok(roleListVOS);
		}
		return R.ok();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R<Boolean> saveRole(SaveRoleDTO dto) {
		SysRole sysRole=BeanUtil.toBean(dto,SysRole.class);
		DaoismUser user = SecurityUtils.getUser();
		if(ObjectUtil.isNotNull(dto.getRoleId())){//更新
			if(dto.getRoleId().equals(dto.getParentId())){
				throw new BizException(100,"请重新选择父级角色!");
			}
			sysRole.setUpdateBy(user.getName()).setUpdateTime(LocalDateTime.now()).setUpdateId(user.getId());
			if(!updateById(sysRole)){
				throw new BizException(ResultCodeEnum.SAVE_ROLE_FAIL);
			}
		}else {
			List<SysRole> list = list(Wrappers.<SysRole>lambdaQuery()
					.eq(SysRole::getRoleCode,dto.getRoleCode()).eq(SysRole::getDelFlag,CommonConstants.NOT_DEL)
					.eq(SysRole::getTenantId,user.getTenantId()));
			if(CollectionUtil.isNotEmpty(list)){
				throw new BizException(100,"角色编码已存在!");
			}
			sysRole.setCreateBy(user.getName()).setCreateTime(LocalDateTime.now())
					.setTenantId(user.getTenantId()).setCreateId(user.getId());
			if(!save(sysRole)){
				throw new BizException(ResultCodeEnum.SAVE_ROLE_FAIL);
			}
		}
		return R.ok(Boolean.TRUE);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R<Boolean> removeRole(DeleteDto dto) {
		SysRole sysRole=sysRoleMapper.selectById(dto.getIds().get(0));
		if(sysRole.getSysFlag()==RoleLevelEnum.ONE.getCode()){
			throw new BizException(ResultCodeEnum.ROLE_IS_SYSTEM);
		}
		//查询角色是否有用户
		List<SysUserRole> sysUserRoleList=sysUserRoleService.list(Wrappers.<SysUserRole>lambdaQuery()
			.eq(SysUserRole::getRoleId,sysRole.getRoleId()));
		if(CollectionUtil.isNotEmpty(sysUserRoleList)){
			throw new BizException(ResultCodeEnum.ROLE_EXIST_USER);
		}
		List<SysRole> userRoleList=sysRoleMapper.selectList(Wrappers.<SysRole>lambdaQuery()
			.eq(SysRole::getParentId,sysRole.getRoleId()).eq(SysRole::getDelFlag,CommonConstants.NOT_DEL));
		if(CollectionUtil.isNotEmpty(userRoleList)){
			throw new BizException(ResultCodeEnum.ROLE_EXIST_CHILD);
		}
		sysRole.setDelFlag(CommonConstants.ONE);
		if(!updateById(sysRole)){
			throw new BizException(ResultCodeEnum.ROLE_DELETE_FAIL);
		}
		return R.ok(Boolean.TRUE);
	}

	@Override
	public List<RoleUserListVO> getRoleUserList(RoleExistUserPageDTO dto) {
		dto.setTenantId(SecurityUtils.getUser().getTenantId());
		DataPermissionVO vo=sysUserService.getDataPermisston(CommonConstants.ZERO,MenuEnum.SYSTEM_ROLE.getCode(),scopeIds);
		// 数据权限
		dto.setUserAll(vo.getUserAll());
		dto.setUserList(vo.getUserList());
		return sysUserMapper.selectRoleUserList(dto);
	}



	@Override
	@Transactional(rollbackFor = Exception.class)
	public R<Boolean> saveRoleUser(RoleUserSaveDTO dto) {
		List<SysUserRole> list=new ArrayList<>();
		DataPermissionVO vo=sysUserService.getDataPermisston(CommonConstants.ZERO,MenuEnum.SYSTEM_ROLE.getCode(),scopeIds);
		sysUserRoleService.remove(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getRoleId,dto.getRoleId()).in(SysUserRole::getUserId,vo.getUserList()));
		if(CollectionUtil.isNotEmpty(dto.getUserIds())){
			dto.getUserIds().forEach(item ->{
				SysUserRole	 sysUserRole=new SysUserRole(item,dto.getRoleId());
				list.add(sysUserRole);
			});
			if(!sysUserRoleService.saveBatch(list)){
				throw new BizException(ResultCodeEnum.ROLE_ADD_USER_FAIL);
			}
		}
		return R.ok(Boolean.TRUE);
	}

	@Override
	public List<RoleMenuTree> getRoleMenuTreeByRoleId(RoleMenuTreeSelectDTO dto) {
		//todo： 需要查询当前用户哪个角色拥有角色管理权限，取有角色管理的角色，后面统一加
		//查询当前用户角色所拥有的菜单
		List<UserRoleMenuVO> userRoleMenuVOS=sysRoleMapper.getUserRoleMenus(SecurityUtils.getRoles());
		//查询要分配的角色已拥有的菜单按钮
		List<SysRoleMenu> sysRoleMenus=roleMenuService.list(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId,dto.getRoleId()));
		List<RoleMenuTreeVO> roleMenuTreeVOList=new ArrayList<>();
		userRoleMenuVOS.forEach(item ->{
			RoleMenuTreeVO vo=BeanUtil.toBean(item,RoleMenuTreeVO.class);
			if(sysRoleMenus.stream().filter(v -> v.getMenuId().equals(item.getMenuId())).findFirst().isPresent()){
				vo.setKeepAlive(CommonConstants.ONE);
			}
			vo.setTypeName(MenuButtomEnum.get(item.getType()).getDescription());
			roleMenuTreeVOList.add(vo);
		});
		return TreeUtil.buildRoleMenuTree(roleMenuTreeVOList, CommonConstants.MENU_TREE_ROOT_ID);
	}



	@Override
	@Transactional(rollbackFor = Exception.class)
	public R<Boolean> saveRoleMenu(RoleMenuDTO dto) {
		//删除原有的菜单/按钮权限
		roleMenuService.remove(Wrappers.<SysRoleMenu>query().lambda().eq(SysRoleMenu::getRoleId, dto.getRoleId()));
		List<SysRoleMenu> list=new ArrayList<>();
		dto.getMenuIds().forEach(item ->{
			list.add(new SysRoleMenu(dto.getRoleId(),item));
		});
		if(!roleMenuService.saveBatch(list)){
			throw new BizException(ResultCodeEnum.DATA_UPDATE_ERROR);
		}
		return R.ok(Boolean.TRUE);
	}

}
